package org.idea.qiyu.framework.mybatis.config;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.idea.qiyu.framework.mybatis.mapper.UserMapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * @Author linhao
 * @Date created in 10:11 上午 2021/10/7
 */
@EnableConfigurationProperties({MyBatisProperties.class})
@Configuration
public class MyBatisAutoConfiguration implements ImportBeanDefinitionRegistrar,InitializingBean, ApplicationContextAware {

    private static PooledDataSource pooledDataSource;

    private ApplicationContext applicationContext;

    private SqlSession sqlSession;

    private SqlSessionFactory sqlSessionFactory;

    @Override
    public void afterPropertiesSet() throws Exception {
        if (pooledDataSource == null) {
            pooledDataSource = new PooledDataSource();
            MyBatisProperties myBatisProperties = applicationContext.getBean(MyBatisProperties.class);
            pooledDataSource.setDriver(myBatisProperties.getDriverName());
            pooledDataSource.setDefaultAutoCommit(true);
            pooledDataSource.setPassword(myBatisProperties.getPassword());
            pooledDataSource.setUsername(myBatisProperties.getUsername());
            pooledDataSource.setUrl(myBatisProperties.getUrl());

            TransactionFactory transactionFactory = new JdbcTransactionFactory();
            Environment environment = new Environment("development",transactionFactory,pooledDataSource);
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(environment);
//            Map<String,Object> daoBeanMap = applicationContext.getBeansWithAnnotation(Mapper.class);
//            for (String beanName : daoBeanMap.keySet()) {
//                Object object = UserMapper;
                Type[] types = UserMapper.class.getGenericInterfaces();
                Type genericInterface = types[0];
                ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                String typeName = parameterizedType.getActualTypeArguments()[0].getTypeName();
                Class<?> clazz = Class.forName(typeName);
                configuration.getTypeAliasRegistry().registerAlias(clazz);
                configuration.addMapper(UserMapper.class);
//            }
            this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
            this.sqlSession = sqlSessionFactory.openSession();
            MybatisBeanWrapper<UserMapper> mybatisBeanWrapper = new MybatisBeanWrapper<>();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            mybatisBeanWrapper.setObject(userMapper);
            AnnotationConfigServletWebServerApplicationContext annotationConfigServletWebServerApplicationContext = (AnnotationConfigServletWebServerApplicationContext) applicationContext;
            annotationConfigServletWebServerApplicationContext.registerBean("userMapper",MybatisBeanWrapper.class,mybatisBeanWrapper);
        }
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
